package kr.ac.skhu.m.util;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

public class EncodingUtil {

	/* public query parsing method */
	public static String getParamterSafely(String queryString, String key) {
		if (StringUtils.isEmpty(queryString)) {
			return "";
		}

		try {
			String safeQueryString = urlDecodeSafely(queryString);
			return getParameter(safeQueryString, key);
		} catch (UnsupportedEncodingException e) {
			//ignore
			e.printStackTrace();
		}
		return "";
	}

	/* URLDecoding 수행 */
	private static String urlDecodeSafely(String queryString)
			throws UnsupportedEncodingException {
		if (StringUtils.isEmpty(queryString))
			return "";
		byte[] src = queryString.getBytes("ISO-8859-1");
		byte[] bytes = urlDecode(src);
		//String charset = guessCharset(bytes);
		String charset = CharsetDetector.detect(bytes);
		return new String(bytes, charset);
	}

	/* 헥사코드를 bytes로 변환 */
	private static byte[] urlDecode(byte[] data)
			throws UnsupportedEncodingException {
		int ix = 0;
		int ox = 0;
		while (ix < data.length) {
			byte c = data[ix++];
			switch ((char) c) {
			case '+':
				data[ox++] = (byte) ' ';
				break;
			case '%':
				data[ox++] = (byte) ((convertHexDigit(data[ix++]) << 4)
						+ convertHexDigit(data[ix++]));
				break;
			default:
				data[ox++] = c;
			}
		}

		return ArrayUtils.subarray(data, 0, ox);
	}

	/* 헥사코드 변환 */
	private static byte convertHexDigit(byte b) {
		if ((b >= '0') && (b <= '9'))
			return (byte) (b - '0');
		if ((b >= 'a') && (b <= 'f'))
			return (byte) (b - 'a' + 10);
		if ((b >= 'A') && (b <= 'F'))
			return (byte) (b - 'A' + 10);
		return 0;
	}

	/* 재석님의 캐릭터셋 추측하는 메소드 */
	private static String guessCharset(byte[] bytes) {
		try {
			CharsetDecoder decoder = Charset.forName("MS949").newDecoder();
			ByteBuffer bb = ByteBuffer.wrap(bytes);
			decoder.decode(bb);
			bb.clear();
			return "MS949";
		} catch (Exception e) {
			return "UTF-8";
		}
	}

	/* 쿼리 문자열에서 특정 키의 값을 가져온다. */
	private static String getParameter(String safeQueryString, String key) {
		String parameters[] = safeQueryString.split("&");
		if (parameters != null) {
			for (String parameter : parameters) {
				if (parameter.startsWith(key + "=")) {
					return parameter.replaceFirst(key + "=", "");
				}
			}
		}
		return "";
	}

}
